#include "inc.h"
#include <algorithm>

#define DETECT_BUFFER_SIZE 0x20000

typedef struct
{
	int confidence;
	int x, y, w, h;
} point_t;

string process(const string& filename, const string& base_path)
{
	Mat image = imread(filename);
	if (image.empty())return "";

	int* pResults = nullptr;
	auto* pBuffer = (unsigned char*)malloc(DETECT_BUFFER_SIZE);
	if (!pBuffer) return "";

	pResults = facedetect_cnn(pBuffer, (unsigned char*)(image.ptr(0)), image.cols, image.rows, (int)image.step);

	unsigned cnt = (pResults ? *pResults : 0);
	if (cnt == 0)
	{
		free(pBuffer);
		return "";
	}

	vector<point_t> points;
	for (int i = 0; i < cnt; i++)
	{
		short* p = ((short*)(pResults + 1)) + 142 * i;
		int confidence = p[0];
		if (confidence < 90) continue;

		points.push_back({ confidence, p[1], p[2], p[3], p[4] });
	}

	free(pBuffer);

	if (points.empty())return "";
	sort(points.begin(), points.end(), [](const point_t& a, const point_t& b) -> bool
	{
	  return a.confidence > b.confidence;
	});

	Mat result_image = image.clone();
	auto point = points[0];
	int margin = 20;
	point.h = min(result_image.rows, point.y + point.h + margin) - point.y;
	point.w = min(result_image.cols, point.x + point.w + margin) - point.x;
	point.x = max(0, point.x - margin);
	point.y = max(0, point.y - margin);
	result_image = result_image(Rect(point.x, point.y, point.w, point.h));
	resize(result_image, result_image, Size(224, 224), 0, 0, INTER_CUBIC);

	auto raw_path = fs::path(filename);
	auto file = raw_path.filename().string();
	replace(file.begin(), file.end(), '_', ' ');
	vector<std::string> filenames;
	stringstream ss(file);
	string tmp;
	while (ss >> tmp) filenames.push_back(tmp);
	if (filenames.size() != 3) return "";

	auto path = std::filesystem::path(base_path);
	path /= filenames[0]; // X
	path /= filenames[1]; // Y
	std::filesystem::create_directories(path);

	path /= raw_path.filename().replace_extension("").string(); // X_Y_i
	path += ".jpg";

	imwrite(path.string(), result_image);

	return path.string();
}